﻿using Fast;
using Fast.NormalizeActionResult;
using Microsoft.AspNetCore.Mvc.Abstractions;
using System.Reflection;
using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Mvc.Filters
{
    /// <summary>
    /// 规范返回结果过滤器
    /// </summary>
    [SkipScan]
    public class NormalizeActionResultFilter : IAsyncActionFilter
    {
        private readonly IActionResultProvider _actionResultProvider;
        public NormalizeActionResultFilter(IActionResultProvider actionResultProvider)
        {
            _actionResultProvider = actionResultProvider;
        }

        /// <summary>
        /// 处理规范化结果
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var actionExecutedContext = await next();

            if (!context.ActionDescriptor.IsControllerAction()) return;

            var actionDescriptor = context.ActionDescriptor.AsControllerActionDescriptor();

            if (actionDescriptor.MethodInfo.GetCustomAttribute<NonNormalizeAttribute>() != null) return;

            IActionResult actionResult = default;

            if (actionExecutedContext.Result is BadRequestObjectResult badRequestObjectResult)
            {
                // 解析验证消息
                var message = badRequestObjectResult.Value?.ToString();

                actionResult = _actionResultProvider.GetValidateFailedResult(context, new ValidationMetadata(message));

                // 打印验证失败信息
                App.PrintToMiniProfiler("validation", "Failed", $"Validation Failed:\r\n{message}", true);
            }
            else
            {
                if (CheckActionResult(actionExecutedContext.Result, out var data))
                {
                    actionResult = _actionResultProvider.GetSucceededResult(actionExecutedContext, data);
                }
            }
            if (actionResult == null) return;

            actionExecutedContext.Result = actionResult;
        }

        private bool CheckActionResult(IActionResult result, out object data)
        {
            data = result switch
            {
                // 处理内容结果
                ContentResult content => content.Content,
                // 处理对象结果
                ObjectResult obj => obj.Value,
                // 处理 JSON 对象
                JsonResult json => json.Value,
                _ => null
            };

            return data != null;
        }
    }
}
